﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Linq.Dynamic;
using Hxsoft.AppV1;

namespace Hxsoft.AppV1.Module
{
	/// <summary>
	/// Resources 类。
	/// </summary>
	public static partial class Resources
	{
		public class CodeId
		{
			public Guid CategoryId { get; set; }
			public int? SiteId { get; set; }
			public string ResourceCode { get; set; }
		}



		#region GetIdentifier
		/// <summary>
		/// 根据指定的信息获取资源标识。
		/// </summary>
		/// <param name="o">资源的集合。</param>
		/// <param name="categoryId">所属类别标识。</param>
		/// <param name="siteId">所属站点标识。</param>
		/// <param name="resourceCode">资源代码。</param>
		/// <returns>指定的资源的标识。</returns>
		internal static Guid? GetIdentifier(this System.Data.Linq.Table<Resource> o, Guid categoryId, int? siteId, string resourceCode)
		{
			var q = from r in o
					where r.CategoryId == categoryId
					select r;

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);
			else
				q = q.Where(p => p.SiteId == null);

			if (!string.IsNullOrEmpty(resourceCode))
				q = q.Where(p => p.ResourceCode == resourceCode);
			else
				q = q.Where(p => p.ResourceCode == null);

			return q.Select(p => (Guid?)p.ResourceId).SingleOrDefault();
		}

		/// <summary>
		/// 根据指定的信息获取资源标识。
		/// </summary>
		/// <param name="categoryId">所属类别标识。</param>
		/// <param name="siteId">所属站点标识。</param>
		/// <param name="resourceCode">资源代码。</param>
		/// <returns>指定的资源的标识。</returns>
		public static Guid? GetIdentifier(Guid categoryId, int? siteId, string resourceCode)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.Resources.GetIdentifier(categoryId, siteId, resourceCode);
		}
		#endregion



		#region GetRoots
		public static List<Resource> GetRoots()
		{
			return GetRoots(false);
		}

		public static List<Resource> GetRoots(Guid categoryId)
		{
			return GetRoots(categoryId, false);
		}

		public static List<Resource> GetRoots(Guid categoryId, int? siteId)
		{
			return GetRoots(categoryId, siteId, false);
		}



		public static List<Resource> GetRoots(bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;
			return dc.Resources.GetRoots();
		}

		public static List<Resource> GetRoots(Guid categoryId, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;
			return dc.Resources.GetRoots(categoryId);
		}

		public static List<Resource> GetRoots(Guid categoryId, int? siteId, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;
			return dc.Resources.GetRoots(categoryId, siteId);
		}



		public static List<Resource> GetRoots(this System.Data.Linq.Table<Resource> o)
		{
			return (from p in o where p.ParentResourceId == null select p).ToList(); ;
		}

		public static List<Resource> GetRoots(this System.Data.Linq.Table<Resource> o, Guid categoryId)
		{
			return (from p in o where p.CategoryId == categoryId && p.ParentResourceId == null select p).ToList();
		}

		public static List<Resource> GetRoots(this System.Data.Linq.Table<Resource> o, Guid categoryId, int? siteId)
		{
			var q = from p in o
					where p.CategoryId == categoryId && p.ParentResourceId == null
					select p;
			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);
			else
				q = q.Where(p => p.SiteId == null);
			return q.ToList();
		}
		#endregion



		#region GetItems
		public static List<Resource> GetItems(this System.Data.Linq.Table<Resource> o, ICollection<Guid> resourceIds)
		{
			if (resourceIds == null) return null;
			if (resourceIds.Count <= 0) return new List<Resource>();
			return (from p in o where resourceIds.Contains(p.ResourceId) select p).ToList();
		}

		public static List<Resource> GetItems(List<Guid> resourceIds)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			return dc.Resources.GetItems(resourceIds);
		}

		public static List<Resource> GetItems(this System.Data.Linq.Table<Resource> o, ICollection<CodeId> resourceIds)
		{
			if (resourceIds == null) return null;
			if (resourceIds.Count <= 0) return new List<Resource>();
			var q = from p in o
					select p;

			if (resourceIds != null)
			{
				string subQuery = "";
				foreach (var resourceId in resourceIds)
					subQuery += (string.IsNullOrEmpty(subQuery) ? "" : " || ") + @"(CategoryId.ToString() == """ + resourceId.CategoryId + @""" && SiteId == " + (resourceId.SiteId.HasValue ? resourceId.SiteId.ToString() : "null") + @" && ResourceCode == """ + resourceId.ResourceCode.Replace("\"", "\\\"") + @""")";
				q = q.Where(subQuery);
			}

			return q.ToList();
		}

		public static List<Resource> GetItems(ICollection<CodeId> resourceIds)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			return dc.Resources.GetItems(resourceIds);
		}
		#endregion



		#region GetItem
		/// <summary>
		/// 根据指定的信息获取资源。
		/// </summary>
		/// <param name="o">资源的集合。</param>
		/// <param name="categoryId">所属类别标识。</param>
		/// <param name="siteId">所属站点标识。</param>
		/// <param name="resourceCode">资源代码。</param>
		/// <returns>指定的资源。</returns>
		internal static Resource GetItem(this System.Data.Linq.Table<Resource> o, Guid categoryId, int? siteId, string resourceCode)
		{
			var q = from p in o where p.CategoryId == categoryId select p;

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);
			else
				q = q.Where(p => p.SiteId == null);

			if (!string.IsNullOrEmpty(resourceCode))
				q = q.Where(p => p.ResourceCode == resourceCode);
			else
				q = q.Where(p => p.ResourceCode == null);

			return q.SingleOrDefault();
		}

		/// <summary>
		/// 根据指定的信息获取资源。
		/// </summary>
		/// <param name="categoryId">所属类别标识。</param>
		/// <param name="siteId">所属站点标识。</param>
		/// <param name="resourceCode">资源代码。</param>
		/// <param name="trackObject">是否跟踪对象状态。</param>
		/// <returns>指定的资源。</returns>
		public static Resource GetItem(Guid categoryId, int? siteId, string resourceCode, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			return dc.Resources.GetItem(categoryId, siteId, resourceCode);
		}

		/// <summary>
		/// 根据指定的信息获取资源。
		/// </summary>
		/// <param name="categoryId">所属类别标识。</param>
		/// <param name="siteId">所属站点标识。</param>
		/// <param name="resourceCode">资源代码。</param>
		/// <returns>指定的资源。</returns>
		public static Resource GetItem(Guid categoryId, int? siteId, string resourceCode)
		{
			return GetItem(categoryId, siteId, resourceCode, false);
		}

		/// <summary>
		/// 根据资源标识获取资源。
		/// </summary>
		/// <param name="o">资源的集合。</param>
		/// <param name="id">资源的标识。</param>
		/// <returns>指定的资源。</returns>
		internal static Resource GetItem(this System.Data.Linq.Table<Resource> o, Guid id)
		{
			return o.SingleOrDefault(p => p.ResourceId == id);
		}

		/// <summary>
		/// 根据资源标识获取资源。
		/// </summary>
		/// <param name="id">资源的标识。</param>
		/// <param name="trackObject">是否跟踪对象状态。</param>
		/// <returns>指定的资源。</returns>
		public static Resource GetItem(Guid id, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			return dc.Resources.GetItem(id);
		}

		/// <summary>
		/// 根据资源标识获取资源。
		/// </summary>
		/// <param name="id">资源的标识。</param>
		/// <returns>指定的资源。</returns>
		public static Resource GetItem(Guid id)
		{
			return GetItem(id, false);
		}
		#endregion
	}



	/// <summary>
	/// Resources 类操作部分。
	/// </summary>
	public static partial class Resources
	{
		#region Register
		/// <summary>
		/// 注册资源。
		/// </summary>
		/// <param name="registerResource">注册的资源。</param>
		/// <returns>注册的资源。</returns>
		internal static Resource Register(Resource registerResource)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Resource resource = dc.Resources.GetItem(registerResource.CategoryId, registerResource.SiteId, registerResource.ResourceCode);

			if (resource == null)
			{
				resource = registerResource.ToNewEntity<Resource>();
				dc.Resources.InsertOnSubmit(resource);
				dc.SubmitChanges();
			}
			else
			{
				if (resource.ParentResourceId != registerResource.ParentResourceId || resource.ResourceName != registerResource.ResourceName || resource.Description != registerResource.Description)
				{
					// 修正数据，以确保数据的正确性
					resource.ParentResourceId = registerResource.ParentResourceId;
					resource.ResourceName = registerResource.ResourceName;
					resource.Description = registerResource.Description;

					try
					{
						dc.SubmitChanges(ConflictMode.ContinueOnConflict);
					}
					catch (ChangeConflictException e)
					{
						foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
							occ.Resolve(RefreshMode.KeepCurrentValues);
					}
				}
			}

			// 返回只读数据
			return registerResource.FillByEntity(resource);
		}
		#endregion



		#region Delete
		#region internal Delete
		internal static void Delete(GenericModuleDataContext dc, Resource resource)
		{
			Resources.DeleteByParent(dc, resource);	// 删除关联数据
			Permissions.DeleteByParent(dc, resource);	// 删除关联数据
			dc.Resources.DeleteOnSubmit(resource);
		}

		internal static void DeleteByParent(GenericModuleDataContext dc, Resource parent)
		{
			IEnumerable<Resource> e = parent.Children.AsEnumerable();
			foreach (Resource i in e)
				Delete(dc, i);
		}

		internal static void DeleteByParent(GenericModuleDataContext dc, ResourceCategory parent)
		{
			IEnumerable<Resource> e = parent.Resources.AsEnumerable();
			foreach (Resource i in e)
				Delete(dc, i);
		}
		#endregion
		#endregion
	}
}